home *** CD-ROM | disk | FTP | other *** search
/ Aminet 30 / Aminet 30 (1999)(Schatztruhe)[!][Apr 1999].iso / Aminet / gfx / misc / gnuplot-3.7src.lha / gnuplot-3.7src / gnuplot-3.7.lha / gnuplot-3.7 / parse.c < prev    next >
C/C++ Source or Header  |  1998-11-19  |  14KB  |  649 lines

  1. #ifndef lint
  2. static char *RCSid = "$Id: parse.c,v 1.62 1998/06/18 14:55:13 ddenholm Exp $";
  3. #endif
  4.  
  5. /* GNUPLOT - parse.c */
  6.  
  7. /*[
  8.  * Copyright 1986 - 1993, 1998   Thomas Williams, Colin Kelley
  9.  *
  10.  * Permission to use, copy, and distribute this software and its
  11.  * documentation for any purpose with or without fee is hereby granted,
  12.  * provided that the above copyright notice appear in all copies and
  13.  * that both that copyright notice and this permission notice appear
  14.  * in supporting documentation.
  15.  *
  16.  * Permission to modify the software is granted, but not the right to
  17.  * distribute the complete modified source code.  Modifications are to
  18.  * be distributed as patches to the released version.  Permission to
  19.  * distribute binaries produced by compiling modified sources is granted,
  20.  * provided you
  21.  *   1. distribute the corresponding source modifications from the
  22.  *    released version in the form of a patch file along with the binaries,
  23.  *   2. add special version identification to distinguish your version
  24.  *    in addition to the base release version number,
  25.  *   3. provide your name and address as the primary contact for the
  26.  *    support of your modified version, and
  27.  *   4. retain our contact information in regard to use of the base
  28.  *    software.
  29.  * Permission to distribute the released version of the source code along
  30.  * with corresponding source modifications in the form of a patch file is
  31.  * granted with same provisions 2 through 4 for binary distributions.
  32.  *
  33.  * This software is provided "as is" without express or implied warranty
  34.  * to the extent permitted by applicable law.
  35. ]*/
  36.  
  37. #include <signal.h>
  38. #include "plot.h"
  39. #include "help.h"
  40. #include <setjmp.h>
  41.  
  42. RETSIGTYPE fpe __PROTO((int an_int));
  43. static void extend_at __PROTO((void));
  44. static union argument *add_action __PROTO((enum operators sf_index));
  45. static void express __PROTO((void));
  46. static void xterm __PROTO((void));
  47. static void aterm __PROTO((void));
  48. static void bterm __PROTO((void));
  49. static void cterm __PROTO((void));
  50. static void dterm __PROTO((void));
  51. static void eterm __PROTO((void));
  52. static void fterm __PROTO((void));
  53. static void gterm __PROTO((void));
  54. static void hterm __PROTO((void));
  55. static void factor __PROTO((void));
  56. static void xterms __PROTO((void));
  57. static void aterms __PROTO((void));
  58. static void bterms __PROTO((void));
  59. static void cterms __PROTO((void));
  60. static void dterms __PROTO((void));
  61. static void eterms __PROTO((void));
  62. static void fterms __PROTO((void));
  63. static void gterms __PROTO((void));
  64. static void hterms __PROTO((void));
  65. static void iterms __PROTO((void));
  66. static void unary __PROTO((void));
  67.  
  68. static struct at_type *at = NULL;
  69. static int at_size = 0;
  70. #if defined(_Windows) && !defined(WIN32)
  71. static jmp_buf far fpe_env;
  72. #else
  73. static jmp_buf fpe_env;
  74. #endif
  75.  
  76. #define dummy (struct value *) 0
  77.  
  78. RETSIGTYPE fpe(an_int)
  79. int an_int;
  80. {
  81. #if defined(MSDOS) && !defined(__EMX__) && !defined(DJGPP) && !defined(_Windows) || defined(DOS386)
  82.     /* thanks to lotto@wjh12.UUCP for telling us about this  */
  83.     _fpreset();
  84. #endif
  85.  
  86. #ifdef OS2
  87.     (void) signal(an_int, SIG_ACK);
  88. #else
  89.     (void) signal(SIGFPE, (sigfunc) fpe);
  90. #endif
  91.     undefined = TRUE;
  92.     longjmp(fpe_env, TRUE);
  93. }
  94.  
  95.  
  96. #ifdef apollo
  97. #include <apollo/base.h>
  98. #include <apollo/pfm.h>
  99. #include <apollo/fault.h>
  100.  
  101. /*
  102.  * On an Apollo, the OS can signal a couple errors that are not mapped into
  103.  * SIGFPE, namely signalling NaN and branch on an unordered comparison.  I
  104.  * suppose there are others, but none of these are documented, so I handle
  105.  * them as they arise. 
  106.  *
  107.  * Anyway, we need to catch these faults and signal SIGFPE. 
  108.  */
  109.  
  110. pfm_$fh_func_val_t apollo_sigfpe(pfm_$fault_rec_t & fault_rec)
  111. {
  112.     kill(getpid(), SIGFPE);
  113.     return pfm_$continue_fault_handling;
  114. }
  115.  
  116. apollo_pfm_catch()
  117. {
  118.     status_$t status;
  119.     pfm_$establish_fault_handler(fault_$fp_bsun, pfm_$fh_backstop,
  120.                  apollo_sigfpe, &status);
  121.     pfm_$establish_fault_handler(fault_$fp_sig_nan, pfm_$fh_backstop,
  122.                  apollo_sigfpe, &status);
  123. }
  124. #endif
  125.  
  126.  
  127. void evaluate_at(at_ptr, val_ptr)
  128. struct at_type *at_ptr;
  129. struct value *val_ptr;
  130. {
  131.     double temp;
  132.  
  133.     undefined = FALSE;
  134.     errno = 0;
  135.     reset_stack();
  136.  
  137. #ifndef DOSX286
  138.     if (setjmp(fpe_env))
  139.     return;            /* just bail out */
  140.     (void) signal(SIGFPE, (sigfunc) fpe);
  141. #endif
  142.  
  143.     execute_at(at_ptr);
  144.  
  145. #ifndef DOSX286
  146.     (void) signal(SIGFPE, SIG_DFL);
  147. #endif
  148.  
  149.     if (errno == EDOM || errno == ERANGE) {
  150.     undefined = TRUE;
  151.     } else if (!undefined) {    /* undefined (but not errno) may have been set by matherr */
  152.     (void) pop(val_ptr);
  153.     check_stack();
  154.     /* At least one machine (ATT 3b1) computes Inf without a SIGFPE */
  155.     temp = real(val_ptr);
  156.     if (temp > VERYLARGE || temp < -VERYLARGE) {
  157.         undefined = TRUE;
  158.     }
  159.     }
  160. #if defined(NeXT) || defined(ultrix)
  161.     /*
  162.      * linux was able to fit curves which NeXT gave up on -- traced it to
  163.      * silently returning NaN for the undefined cases and plowing ahead
  164.      * I can force that behavior this way.  (0.0/0.0 generates NaN)
  165.      */
  166.     if (undefined && (errno == EDOM || errno == ERANGE)) {    /* corey@cac */
  167.     undefined = FALSE;
  168.     errno = 0;
  169.     Gcomplex(val_ptr, 0.0 / 0.0, 0.0 / 0.0);
  170.     }
  171. #endif /* NeXT || ultrix */
  172. }
  173.  
  174.  
  175. struct value *
  176.  const_express(valptr)
  177. struct value *valptr;
  178. {
  179.     register int tkn = c_token;
  180.  
  181.     if (END_OF_COMMAND)
  182.     int_error("constant expression required", c_token);
  183.  
  184.     /* div - no dummy variables in a constant expression */
  185.     dummy_func = NULL;
  186.  
  187.     evaluate_at(temp_at(), valptr);    /* run it and send answer back */
  188.     if (undefined) {
  189.     int_error("undefined value", tkn);
  190.     }
  191.     return (valptr);
  192. }
  193.  
  194.  
  195. /* if dummy_dunc == NULL on entry, do not attempt to compile dummy variables
  196.  * - div
  197.  */
  198. struct at_type *
  199.  temp_at()
  200. {
  201.     /* build a static action table and return its
  202.      * pointer */
  203.  
  204.     if (at != NULL) {
  205.     free(at);
  206.     at = NULL;
  207.     }
  208.     at = (struct at_type *) gp_alloc(sizeof(struct at_type), "action table");
  209.  
  210.     at->a_count = 0;        /* reset action table !!! */
  211.     at_size = MAX_AT_LEN;
  212.     express();
  213.     return (at);
  214. }
  215.  
  216.  
  217. /* build an action table, put it in dynamic memory, and return its pointer */
  218.  
  219. struct at_type *
  220.  perm_at()
  221. {
  222.     register struct at_type *at_ptr;
  223.     unsigned int len;
  224.  
  225.     (void) temp_at();
  226.     len = sizeof(struct at_type) +
  227.      (int) (at->a_count - MAX_AT_LEN) * (int) sizeof(struct at_entry);
  228.     at_ptr = (struct at_type *) gp_realloc(at, (unsigned long) len, "perm_at");
  229.     at = NULL;            /* invalidate at pointer */
  230.     return (at_ptr);
  231. }
  232.  
  233. static void extend_at()
  234. {
  235.     int newsize = sizeof(struct at_type) + at_size * sizeof(struct at_entry);
  236.  
  237.     at = gp_realloc(at, newsize, "extend_at");
  238.     at_size += MAX_AT_LEN;
  239.     FPRINTF((stderr, "Extending at size to %d\n", at_size));
  240. }
  241.  
  242. /* moved from eval.c, the function is only called from this module */
  243. static union argument *
  244.  add_action(sf_index)
  245. enum operators sf_index;    /* index of p-code function */
  246. {
  247.     if (at->a_count >= at_size) {
  248.     extend_at();
  249.     }
  250.     at->actions[at->a_count].index = sf_index;
  251.     return (&(at->actions[at->a_count++].arg));
  252. }
  253.  
  254.  
  255. static void express()
  256. {                /* full expressions */
  257.     xterm();
  258.     xterms();
  259. }
  260.  
  261. static void xterm()
  262. {                /* ? : expressions */
  263.     aterm();
  264.     aterms();
  265. }
  266.  
  267.  
  268. static void aterm()
  269. {
  270.     bterm();
  271.     bterms();
  272. }
  273.  
  274.  
  275. static void bterm()
  276. {
  277.     cterm();
  278.     cterms();
  279. }
  280.  
  281.  
  282. static void cterm()
  283. {
  284.     dterm();
  285.     dterms();
  286. }
  287.  
  288.  
  289. static void dterm()
  290. {
  291.     eterm();
  292.     eterms();
  293. }
  294.  
  295.  
  296. static void eterm()
  297. {
  298.     fterm();
  299.     fterms();
  300. }
  301.  
  302.  
  303. static void fterm()
  304. {
  305.     gterm();
  306.     gterms();
  307. }
  308.  
  309.  
  310. static void gterm()
  311. {
  312.     hterm();
  313.     hterms();
  314. }
  315.  
  316.  
  317. static void hterm()
  318. {
  319.     unary();            /* - things */
  320.     iterms();            /* * / % */
  321. }
  322.  
  323.  
  324. static void factor()
  325. {
  326.     if (equals(c_token, "(")) {
  327.     c_token++;
  328.     express();
  329.     if (!equals(c_token, ")"))
  330.         int_error("')' expected", c_token);
  331.     c_token++;
  332.     } else if (equals(c_token, "$")) {
  333.     struct value a;
  334.     if (!isanumber(++c_token))
  335.         int_error("Column number expected", c_token);
  336.     convert(&a, c_token++);
  337.     if (a.type != INTGR || a.v.int_val < 0)
  338.         int_error("Positive integer expected", c_token);
  339.     add_action(DOLLARS)->v_arg = a;
  340.     } else if (isanumber(c_token)) {
  341.     /* work around HP 9000S/300 HP-UX 9.10 cc limitation ... */
  342. #if defined(__hpux) && defined(__hp9000s300) && !defined(__GNUC__)
  343.     union argument *foo = add_action(PUSHC);
  344.     convert(&(foo->v_arg), c_token);
  345. #else
  346.     convert(&(add_action(PUSHC)->v_arg), c_token);
  347. #endif
  348.     c_token++;
  349.     } else if (isletter(c_token)) {
  350.     if ((c_token + 1 < num_tokens) && equals(c_token + 1, "(")) {
  351.         enum operators value = standard(c_token);
  352.         if (value) {    /* it's a standard function */
  353.         c_token += 2;
  354.         express();
  355.         if (equals(c_token, ",")) {
  356.             while (equals(c_token, ",")) {
  357.             c_token += 1;
  358.             express();
  359.             }
  360.         }
  361.         if (!equals(c_token, ")"))
  362.             int_error("')' expected", c_token);
  363.         c_token++;
  364.         (void) add_action(value);
  365.         } else {
  366.         enum operators call_type = (int) CALL;
  367.         int tok = c_token;
  368.         c_token += 2;
  369.         express();
  370.         if (equals(c_token, ",")) {
  371.             struct value num_params;
  372.             num_params.type = INTGR;
  373.             num_params.v.int_val = 1;
  374.             while (equals(c_token, ",")) {
  375.             num_params.v.int_val += 1;
  376.             c_token += 1;
  377.             express();
  378.             }
  379.             add_action(PUSHC)->v_arg = num_params;
  380.             call_type = (int) CALLN;
  381.         }
  382.         if (!equals(c_token, ")"))
  383.             int_error("')' expected", c_token);
  384.         c_token++;
  385.         add_action(call_type)->udf_arg = add_udf(tok);
  386.         }
  387.         /* dummy_func==NULL is a flag to say no dummy variables active */
  388.     } else if (dummy_func) {
  389.         if (equals(c_token, c_dummy_var[0])) {
  390.         c_token++;
  391.         add_action(PUSHD1)->udf_arg = dummy_func;
  392.         } else if (equals(c_token, c_dummy_var[1])) {
  393.         c_token++;
  394.         add_action(PUSHD2)->udf_arg = dummy_func;
  395.         } else {
  396.         int i, param = 0;
  397.         for (i = 2; i < MAX_NUM_VAR; i++) {
  398.             if (equals(c_token, c_dummy_var[i])) {
  399.             struct value num_params;
  400.             num_params.type = INTGR;
  401.             num_params.v.int_val = i;
  402.             param = 1;
  403.             c_token++;
  404.             add_action(PUSHC)->v_arg = num_params;
  405.             add_action(PUSHD)->udf_arg = dummy_func;
  406.             break;
  407.             }
  408.         }
  409.         if (!param) {    /* defined variable */
  410.             add_action(PUSH)->udv_arg = add_udv(c_token);
  411.             c_token++;
  412.         }
  413.         }
  414.         /* its a variable, with no dummies active - div */
  415.     } else {
  416.         add_action(PUSH)->udv_arg = add_udv(c_token);
  417.         c_token++;
  418.     }
  419.     }
  420.     /* end if letter */
  421.     else
  422.     int_error("invalid expression ", c_token);
  423.  
  424.     /* add action code for ! (factorial) operator */
  425.     while (equals(c_token, "!")) {
  426.     c_token++;
  427.     (void) add_action(FACTORIAL);
  428.     }
  429.     /* add action code for ** operator */
  430.     if (equals(c_token, "**")) {
  431.     c_token++;
  432.     unary();
  433.     (void) add_action(POWER);
  434.     }
  435. }
  436.  
  437.  
  438.  
  439. static void xterms()
  440. {
  441.     /* create action code for ? : expressions */
  442.  
  443.     if (equals(c_token, "?")) {
  444.     register int savepc1, savepc2;
  445.     register union argument *argptr1, *argptr2;
  446.     c_token++;
  447.     savepc1 = at->a_count;
  448.     argptr1 = add_action(JTERN);
  449.     express();
  450.     if (!equals(c_token, ":"))
  451.         int_error("expecting ':'", c_token);
  452.     c_token++;
  453.     savepc2 = at->a_count;
  454.     argptr2 = add_action(JUMP);
  455.     argptr1->j_arg = at->a_count - savepc1;
  456.     express();
  457.     argptr2->j_arg = at->a_count - savepc2;
  458.     }
  459. }
  460.  
  461.  
  462. static void aterms()
  463. {
  464.     /* create action codes for || operator */
  465.  
  466.     while (equals(c_token, "||")) {
  467.     register int savepc;
  468.     register union argument *argptr;
  469.     c_token++;
  470.     savepc = at->a_count;
  471.     argptr = add_action(JUMPNZ);    /* short-circuit if already
  472.                      * TRUE */
  473.     aterm();
  474.     argptr->j_arg = at->a_count - savepc;    /* offset for jump */
  475.     (void) add_action(BOOLE);
  476.     }
  477. }
  478.  
  479.  
  480. static void bterms()
  481. {
  482.     /* create action code for && operator */
  483.  
  484.     while (equals(c_token, "&&")) {
  485.     register int savepc;
  486.     register union argument *argptr;
  487.     c_token++;
  488.     savepc = at->a_count;
  489.     argptr = add_action(JUMPZ);    /* short-circuit if already
  490.                      * FALSE */
  491.     bterm();
  492.     argptr->j_arg = at->a_count - savepc;    /* offset for jump */
  493.     (void) add_action(BOOLE);
  494.     }
  495. }
  496.  
  497.  
  498. static void cterms()
  499. {
  500.     /* create action code for | operator */
  501.  
  502.     while (equals(c_token, "|")) {
  503.     c_token++;
  504.     cterm();
  505.     (void) add_action(BOR);
  506.     }
  507. }
  508.  
  509.  
  510. static void dterms()
  511. {
  512.     /* create action code for ^ operator */
  513.  
  514.     while (equals(c_token, "^")) {
  515.     c_token++;
  516.     dterm();
  517.     (void) add_action(XOR);
  518.     }
  519. }
  520.  
  521.  
  522. static void eterms()
  523. {
  524.     /* create action code for & operator */
  525.  
  526.     while (equals(c_token, "&")) {
  527.     c_token++;
  528.     eterm();
  529.     (void) add_action(BAND);
  530.     }
  531. }
  532.  
  533.  
  534. static void fterms()
  535. {
  536.     /* create action codes for == and !=
  537.      * operators */
  538.  
  539.     while (TRUE) {
  540.     if (equals(c_token, "==")) {
  541.         c_token++;
  542.         fterm();
  543.         (void) add_action(EQ);
  544.     } else if (equals(c_token, "!=")) {
  545.         c_token++;
  546.         fterm();
  547.         (void) add_action(NE);
  548.     } else
  549.         break;
  550.     }
  551. }
  552.  
  553.  
  554. static void gterms()
  555. {
  556.     /* create action code for < > >= or <=
  557.      * operators */
  558.  
  559.     while (TRUE) {
  560.     /* I hate "else if" statements */
  561.     if (equals(c_token, ">")) {
  562.         c_token++;
  563.         gterm();
  564.         (void) add_action(GT);
  565.     } else if (equals(c_token, "<")) {
  566.         c_token++;
  567.         gterm();
  568.         (void) add_action(LT);
  569.     } else if (equals(c_token, ">=")) {
  570.         c_token++;
  571.         gterm();
  572.         (void) add_action(GE);
  573.     } else if (equals(c_token, "<=")) {
  574.         c_token++;
  575.         gterm();
  576.         (void) add_action(LE);
  577.     } else
  578.         break;
  579.     }
  580.  
  581. }
  582.  
  583.  
  584.  
  585. static void hterms()
  586. {
  587.     /* create action codes for + and - operators */
  588.  
  589.     while (TRUE) {
  590.     if (equals(c_token, "+")) {
  591.         c_token++;
  592.         hterm();
  593.         (void) add_action(PLUS);
  594.     } else if (equals(c_token, "-")) {
  595.         c_token++;
  596.         hterm();
  597.         (void) add_action(MINUS);
  598.     } else
  599.         break;
  600.     }
  601. }
  602.  
  603.  
  604. static void iterms()
  605. {
  606.     /* add action code for * / and % operators */
  607.  
  608.     while (TRUE) {
  609.     if (equals(c_token, "*")) {
  610.         c_token++;
  611.         unary();
  612.         (void) add_action(MULT);
  613.     } else if (equals(c_token, "/")) {
  614.         c_token++;
  615.         unary();
  616.         (void) add_action(DIV);
  617.     } else if (equals(c_token, "%")) {
  618.         c_token++;
  619.         unary();
  620.         (void) add_action(MOD);
  621.     } else
  622.         break;
  623.     }
  624. }
  625.  
  626.  
  627. static void unary()
  628. {
  629.     /* add code for unary operators */
  630.  
  631.     if (equals(c_token, "!")) {
  632.     c_token++;
  633.     unary();
  634.     (void) add_action(LNOT);
  635.     } else if (equals(c_token, "~")) {
  636.     c_token++;
  637.     unary();
  638.     (void) add_action(BNOT);
  639.     } else if (equals(c_token, "-")) {
  640.     c_token++;
  641.     unary();
  642.     (void) add_action(UMINUS);
  643.     } else if (equals(c_token, "+")) {    /* unary + is no-op */
  644.     c_token++;
  645.     unary();
  646.     } else
  647.     factor();
  648. }
  649.